Si vous deviez revivre une époque, vous choisiriez laquelle ? 如果時光倒流,你想回到何時
La Belle Epoque 美好拾光公司 7th, 5
時間總是不斷向前走,每人每刻,都面對著不同的路口,儘管我們都有各自的課題,但相同的是人總在某個深夜,會希望能穿越時間,在某個交錯的緣分中做不同的選擇
.
.
.
你也有想回去的路口嗎?
可惜的是人生沒有重來,那努力讓未來不要留下遺憾吧
但是呢!!! Git 可以喔!!!今天來開始使用 Git 吧,至於為什麼這階段聊 Git,原因很簡單 我想寫小散文 之後的 OOP 概念會比之前的複雜,把 Git 學好,有版控才能寫出更好的 Kotlin 專案(每個語言都是拉XD)
本文結構
創建一個專案,並在 terminal 切換到專案的根目錄,下git init
已設置 git 追蹤此資料夾包含的內容,這時如果下 ls -a
會發現增加了 .git
的檔案
如果想要移除 git 的檔案管理,git 並沒有指令可以 undo git init ,需要手動輸入 rm -rf .git
,個人不喜歡下 rm -rf
但當初的確找了很久,git 是真沒指令處理
初始化後,裡面也會增加一個檔案叫 .gitignore
sample kotlin project
sample web project
他做的是很簡單,就是聲明專案裡哪些檔案或資料夾不要被 git 追蹤,我們可以用 glob 來寫規則
/setting/*.json # 忽略所有 setting 目錄下附檔名是 .json 的檔案
*.txt # 忽略所有附檔名是 .txt 的檔案
而這些設置需要 .gitignore
先被追蹤後才會生效,可以先
git add .gitignore
git commit -m "Add git ignore"
完成之後,就可以看到 ide 裡面,會將沒被追蹤的檔案以不同顏色區分,通常我們會將依賴的套件資源以及需要隱藏的變數(Api key)也加入 .gitignore
裡面
當然你也可以使用 git-crypt 來加密
git branch dev //新增 dev 分支
//or
git checkout -b feat// 新增 feat 分支並切換過去
git branch -d feat //可刪除以合併過的 feat 分支
git branch -D test //可刪除未合併過的 test 分支
git commit 是要讓其他開發者,可以透過訊息了解這個節點更動了什麼,如果團隊有固定格式的話請照固定格式,這邊分享一下我現在使用的格式
Type:
[type] subject
body
fotter
而實際打出來可能會長這樣
[feat] : 用戶登入功能
需求:
email 用原生格式驗證
密碼以正規表達式驗證
調整項目:
1. EmailValidator.kt,使用 Patterns.EMAIL_ADDRESS 驗證。
2. PasswordValidator.kt,使用後端提供格式驗證。
Reviewed-by: @Team member
Refs #6
請一定描述原始問題,不要假設閱讀者能知道,連你在一個月後都不一定能想起來了
兩者的差異在接合兩個分支時最明顯,假設 dev 上面開了兩個分支,user, payment
user1 -> user2
001100 -> 110011
payment
090909
用 merge 接合的話, git 會取個分支最後的結果,檢查是否有衝突,並新增一個 commit 節點
//user branch
git merge payment
user1 -> user2 -> payment -> merge paymeny into user
001100 -> 110011 -> 090909 -> 686888
用 rebase 接合的話,git 會接
//user branch
git rebase payment
payment -> user1 -> user2
090909 -> 776678 -> 899362
值得注意的是,rebase 會該改 commit 節點紀錄,如果你的節點已經推出去給別人用了,就不建議用 rebase 操作
rebase 本質上是把 user branch 的每個 commit 拿一份去 payment 後面,並重新計算 sha 值,最後再把 user branch 指向 889362
, Head 指向 user branch
jetbrain 的 ide 裡面有內建一些工具,筆者認為最有用的就是 Reformat, Rearrange, Optimize 了,如果透過 ide 下 git commit 也不用特定開 vim 寫訊息,還能自動幫你整理一些 code ,儘管關閉檔案前用快捷鍵整理是禮貌,但筆者這種金魚腦還是靠工具實在
已經 push 出去的 commit 只用 revert 更改,reset, rebase 都會造成平行時空
真正意義上的回去,如果已經 push 出去,而在本地新增其他節點,就會有平行時空出現
001100 -> 110011 -> 066660
$ git reset HEAD^ --hard
001100 -> 110011
revert 是新增一個 內容和 110011
一樣的節點,來取消 066660
所新增的更動
001100 -> 110011 -> 066660
fun 1 -> fun 2 -> note 1
$ git revert HEAD --no-edit
001100 -> 110011 -> 066660 -> 008863
fun 1 -> fun 2 -> note 1 -> Revert note 1
好了,基本知識講完了,來說本文重點 git flow
這什麼意思呢?
總歸是,feature, develop 的 每個 commit 會很小,到release 前會整理一次,master 的 commit 範圍最大,現實專案中可能不會用到全部的 branch
如果 dev 不用留下所有 commit 的話會更簡單點,但先示範麻煩的XD
先基本設置
git init
git add .
git commit -m "init project"
git checkout -b dev
之後增加節點
touch {1..3}
git add 1
git commit -m "one"
git add 2
git commit -m "two"
git add 3
git commit -m "three"
為接合作準備
git checkout -b toBeMerge
git rebase -i master
將 vim 改成
//vim
pick 001100 one
s 110011 two
s 333111 three
離開後跳轉到編輯訊息的 vim
#...
function one
離開後就完成第一步
git checkout master
git merge toBeMerge
git checkout dev
git tag v0.5
git merge feat
git branch -d feat toBeMerge
之後要再開發新功能也是從 dev 開
git checkout -b feat
touch {4..6}
git add 4
git commit -m "four"
git add 5
git commit -m "five"
git add 6
git commit -m "six"
git checkout -b toBeMerge
唯一特別的是
git rebase -i --onto master dev toBeMerge
這段是指,我要把 toBeMerge rebase 到 master 並忽略 dev 已經有的東西,最後將被 rebase 的 bramch 較 toBeMerge
後面就基本一樣
git tag v1.0
最後的 git 會長這樣
好的版控可以讓你的專案井然有條,沒版控的專案及可能會混亂不堪 跟我的人生一樣
Time won't stop for anyone, we all facing different choices in our life, but we all wish to travel back in time, to make a different choice in some moment
.
.
.
Do you have the moment you want to change?
It is pity that we can' do over, but we can do our best to leave leave no regrets 7th, May
But!! Git can travel back in time!! Today we gonna discuss git
Structure
create a project, switch to root in terminal, typegit init
to set up git track this folder, we can check it out by ls -a
to see .git
file
If you want to remove fit, git didn't provide command to undo git init , require type rm -rf .git
After initialize, we also get .gitignore
sample kotlin project
sample web project
It is simple, to declare some file not track by git, we can use glob to define rule
/setting/*.json # ignore all json file under setting folder
*.txt # ignore all .txt file
this setting require .gitignore
track by git
git add .gitignore
git commit -m "Add git ignore"
After that, you can see ide change color of file from ignored and tracked, usually we will ignore dependency folder and hidden variable
for variable you can use git-crypt as optional
git branch dev //create dev branch
//or
git checkout -b feat// create feat branch and checkout
git branch -d feat //delete merged feat branch
git branch -D test //delete unmerged test branch
git commit to for other developers to know changed between commits, if your team has format, please follow it, I will share mine
Type:
[type] subject
body
fotter
a real sample look like
[feat] : User login
Demand:
email validate by native rule
password validate by Regex
Modify:
1. EmailValidator.kt,use Patterns.EMAIL_ADDRESS to validate。
2. PasswordValidator.kt, validate with Regex provided by backend。
Reviewed-by: @Team member
Refs #6
And please describe demand in body
The different between those two is obvious while merge two branch, if dev branch
has two branches user, payment
user1 -> user2
001100 -> 110011
payment
090909
By using merge, git will take the result of each branch, check for conflict and create a new commit
//user branch
git merge payment
user1 -> user2 -> payment -> merge payment into user
001100 -> 110011 -> 090909 -> 686888
By using rebase
//user branch
git rebase payment
payment -> user1 -> user2
090909 -> 776678 -> 899362
git will change commit history, the rebase operator is take commit from user branch
to the end of payment branch
, and calculate sha value, then point user branch
to 889362
, Head to user branch
If your commit already push to remote, only change by revert
, reset, rebase
will change history, and it will cause problem
Really go back to previous commit
001100 -> 110011 -> 066660
$ git reset HEAD^ --hard
001100 -> 110011
By add a new commit same as 110011
, to undo changes in 066660
001100 -> 110011 -> 066660
fun 1 -> fun 2 -> note 1
$ git revert HEAD --no-edit
001100 -> 110011 -> 066660 -> 008863
fun 1 -> fun 2 -> note 1 -> Revert note 1
Alright, the basic knowledge is done, let's move to the point
What does that mean?
In conclusion, each commit in feature, develop will be small scope, commit in master will be the scope between verison, we might not need all branch in reality
If dev branch don't need all commit things will be easy, but let's start will hard one
basic set up
git init
git add .
git commit -m "init project"
git checkout -b dev
create commits
touch {1..3}
git add 1
git commit -m "one"
git add 2
git commit -m "two"
git add 3
git commit -m "three"
prepare for merge
git checkout -b toBeMerge
git rebase -i master
using vim to change
//vim
pick 001100 one
s 110011 two
s 333111 three
edit commit message
#...
function one
first step done
git checkout master
git merge toBeMerge
git checkout dev
git tag v0.5
git merge feat
git branch -d feat toBeMerge
For more demand, we also create a new branch from dev
git checkout -b feat
touch {4..6}
git add 4
git commit -m "four"
git add 5
git commit -m "five"
git add 6
git commit -m "six"
git checkout -b toBeMerge
the one thing different is here
git rebase -i --onto master dev toBeMerge
it means, I gonna rebase tobeMerge
to master
and ignore everything exists in dev
, then named to branch toBeMerge
others are same
git tag v1.0
the result will look like
Good version can make your project clean,
git-scm
為你自己學 Git
伸縮自如的 Git flow
write better commit message